package com.bdv.md.controller;


import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.bdv.md.common.RequestThread;
import com.bdv.md.controller.xmlattribute.Parameter;
import com.bdv.md.controller.xmlattribute.TselTlkm;
import com.bdv.md.controller.xmlattribute.TlkmTsel;
import com.bdv.md.en.ConstantValues;
import com.bdv.md.en.HTTPValues;
import com.bdv.md.en.RequestEn;
import com.bdv.md.en.UrlList;
import com.bdv.md.model.DmTbl;
import com.bdv.md.model.LimTbl;
import com.bdv.md.model.MapTbl;
import com.bdv.md.model.RemTbl;
import com.bdv.md.model.Transaction;
import com.bdv.md.model.TxTbl;
import com.bdv.md.service.DmTblService;
import com.bdv.md.service.JobService;
import com.bdv.md.service.LimTblService;
import com.bdv.md.service.MapTblService;
import com.bdv.md.service.RemTblService;
import com.bdv.md.service.TransactionService;
import com.bdv.md.service.TxTblService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

@Controller
public class MainController {
	private Logger logger = Logger.getLogger(this.getClass());
	
	private static final String INDEX_PAGE = "index";
	
	@Autowired
    private MapTblService mapTblSvc;
	@Autowired
	private TxTblService txTblSvc;
	@Autowired
	private LimTblService limTblSvc;
	@Autowired
	private RemTblService remTblSvc;
	@Autowired
	private DmTblService dmTblSvc;
	@Autowired
	private JobService jobSvc;
	@Autowired
	private TransactionService trxSvc;

	private static Map<String, Semaphore> txSemaphores = new HashMap<String, Semaphore>();
	private static Map<String, String> txStatus = new HashMap<String, String>();
	
	public String waitResponseTxStatus(String txId){
		String response = null;
			try {
				txSemaphores.get(txId).acquire();
				response = txStatus.get(txId);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		return response;
	}
	public void clearWaitResponseVariable(String txId){
		txSemaphores.remove(txId);
		txStatus.remove(txId);
	}
	
	@RequestMapping("/index")
	public ModelAndView homePage(ModelAndView mav){
		mav.setViewName(INDEX_PAGE);				
		return mav;
	}
	
	@RequestMapping("/")
	public @ResponseBody String services(HttpServletRequest req){
		System.out.println("Request come from USSD");
		
		try{
			String xml = getXMLFromRequest(req);
			if(xml!=null) System.out.println("Request Successfully converted to XML: "+xml);
			TselTlkm tselTlkm = parseXMLtoTselTlkm(xml);
			if(tselTlkm!=null) System.out.println("TselTlkm Object: "+tselTlkm);
			
			String type = tselTlkm.getType();
			Parameter param = tselTlkm.getParam();
			
			if( HTTPValues.TYPE_TOPUP_RESULT.equal(type) )return responseToken(param);
			else if ( HTTPValues.TYPE_METER_DATA.equal(type) )return responseMeter(param);
			else if ( HTTPValues.TYPE_CREDIT_LIMIT_RESULT.equal(type) )return responseLimKredit(param);
			else if ( HTTPValues.TYPE_ALERT.equal(type) )return responseAlert(param);
			else if ( HTTPValues.TYPE_TOKEN_HIST_DATA.equal(type) )return responseHisToken(param);
			else if ( HTTPValues.TYPE_BILLING_HIST_DATA.equal(type) )return responseBilHistory(param);
			
			else if ( HTTPValues.TYPE_METER_READING_PP.equal(type)) return responseAMRPP(param);
			else if ( HTTPValues.TYPE_LOAD_PROFILE_PP.equal(type)) return responseLoadProfilePP(param);
			else if ( HTTPValues.TYPE_EVENT_LOG_PP.equal(type)) return responseEventLogPP(param);
			else if ( HTTPValues.TYPE_BILLING_PP.equal(type)) return responseBillingPP(param);
			else if ( HTTPValues.TYPE_ALARM_PP.equal(type)) return responseAlarmPP(param);
			else if ( HTTPValues.TYPE_RECALL_LOAD_PROFILE_PP.equal(type)) return responseRecallLoadProfilePP(param);
			else if ( HTTPValues.TYPE_TIME_SYNC_PP.equal(type)) return responseTimeSyncPP(param);
			else if ( HTTPValues.TYPE_REMOTE_PP.equal(type)) return responseRemotePP(param);
			else if ( HTTPValues.TYPE_SCADA_SYSTEM_PP.equal(type)) return responseScadaSystemPP(param);
			
			return responseResult(type, "0", param.getTrxId());
		}catch(Exception e){
			System.out.println("Error when receive message "+e.getMessage());
			e.printStackTrace();
			return e.getMessage();
		}
	}

	// PRE PAID =======================================================================================================
	
	/**
	 * REQUEST TOKEN METHOD
	 * this will receive any call from MGT, it will send a token request to USSD, 
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by response-token
	 * this will also insert the data of the transaction table [txId, token, mapTblId]
	 */
	@RequestMapping("/request-token")
	public @ResponseBody String requestToken(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		String token = req.getParameter(HTTPValues.NO_TOKEN.getName());
		
		MapTbl updateMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = updateMeter.getMsisdn();
		Integer mapTblId = updateMeter.getMapId();
		TxTbl txTbl = new TxTbl(txId, token, mapTblId);
		txTblSvc.saveOrUpdate(txTbl);
		trxSvc.saveNewTransaction(txId, mapTblId, meterId, Integer.parseInt(ConstantValues.CC_TOKEN_REQUEST.getPLNCode()));
		
		// SENDING REQUEST TO TSEL USSD
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId, token);
		param.setUtilityCode(ConstantValues.CC_TOKEN_REQUEST.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_TOKEN.getName(), param);
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(UrlList.USSD_TOKEN_REQUEST.getUrl(), xml);

		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_TOKEN_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		// END SENDING
		return responseText;
	}

	/**
	 * RESPONSE TOKEN METHOD
	 * this will receive any request call from USSD, that related from the request token that have been sent
	 * this will send a request call to MGT sending all data from USSD
	 * this will also update the data of the transaction table [status,jenisToken,balance,paymentMode]
	 */
	public String responseToken(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		try{
			
			Integer status = Integer.parseInt(param.getSuksesStatus());
			Integer jenisToken = Integer.parseInt(param.getJenisToken());
			String balance = param.getBalanceKWH();
			Integer paymentMode = Integer.parseInt(param.getPaymentMode());
			
			TxTbl txTbl = txTblSvc.findById(txId);
			txTbl.setStatus(status);
			txTbl.setJenisToken(jenisToken);
			txTbl.setBalance(balance);
			txTbl.setPaymentMode(paymentMode);
			txTblSvc.saveOrUpdate(txTbl);
			
			// lyd
			trxSvc.updateTransactionResponse(txId);
			Transaction trx = trxSvc.getTransactionByTrxId(txId);
			Timestamp timeStamp = trx.getResponseTime();
			
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId.toString()));
			nameValuePairs.add(HTTPValues.BALANCE_KWH.getNameValuePair(balance));
			nameValuePairs.add(HTTPValues.PAYMENT_MODE.getNameValuePair(paymentMode.toString()));
			nameValuePairs.add(HTTPValues.TOKEN_TX_STATUS.getNameValuePair(status.toString()));
			nameValuePairs.add(HTTPValues.JENIS_TOKEN.getNameValuePair(jenisToken.toString()));
			nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
			
			String url = UrlList.MGT_TOKEN_REQUEST.getUrl();
			String response = httpRequestPost(url, nameValuePairs);
//			String response = "1";
			System.out.println("Response from MGT: "+response);
			
			return responseResult(HTTPValues.TYPE_TOPUP_RESULT_RESP.getName(), "1",txId);
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_TOPUP_RESULT_RESP.getName(), "0", txId);
		}
	}


	/**
	 * REQUEST METER METHOD
	 * this will receive any meter data request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseMeter
	 */
	@RequestMapping("/request-meter")
	public @ResponseBody String requestMeter(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		System.out.println(requestedMetr.getMapId());
		
		if (requestedMetr.getMsisdn() == null) {
			System.out.println("null");
		}
		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		
		TlkmTsel tselXmlObj = null;
		String url = null;
		if(requestedMetr.getTipePlg().equalsIgnoreCase("2")){
			tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_METER_READING_PP.getName(),param);
			url = UrlList.USSD_AMR_PP_REQUEST.getUrl();
			param.setUtilityCode(ConstantValues.CC_AMR_PP.getPLNCode());
		}else{
			tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_READ_METER.getName(), param);
			url = UrlList.USSD_AMR_REQUEST.getUrl();
			param.setUtilityCode(ConstantValues.CC_AMR.getPLNCode());
		}
		
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), requestedMetr.getMeterId(), Integer.parseInt(param.getUtilityCode().toString()));
		
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(requestedMetr.getTipePlg().equalsIgnoreCase("2")){
			if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_METER_READING_PP_RESP.equal(response.getType()) ){
				responseText = waitResponseTxStatus(txId);
				//responseText = response.getParam().getResponseStatus();
			}else{
				logger.error(response.toString());
				responseText = "-1";
			}
		}else{
			if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_READ_METER_RESP.equal(response.getType()) ){
				responseText = waitResponseTxStatus(txId);
				//responseText = response.getParam().getResponseStatus();
			}else{
				logger.error(response.toString());
				responseText = "-1";
			}
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	/**
	 * RESPONSE METER METHOD
	 * this will be called when a requestMeter call from USSD, related from the request meter that have been sent
	 * this will send a request call to MGT sending all data from USSD
	 * this will also insert the data of the data meter table [DM_TBL]
	 */
	public String responseMeter(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		try{
			String msisdn = param.getMeterNumber();
			String meterId = param.getMeterID();
			String balanceKWH = param.getBalanceKWH();
			String totalUsage = param.getTotalUsage();
			List<String> voltageRST = getParts(param.getVoltageRST(), 5);
			String voltageR = voltageRST.get(0);
			String voltageS = voltageRST.get(1);
			String voltageT = voltageRST.get(2);
			List<String> arusRST = getParts(param.getArusRST(), 7);
			String arusR = arusRST.get(0);
			String arusS = arusRST.get(1);
			String arusT = arusRST.get(2);
			String powerFactor = param.getPowerFactor();
			String dayaInstant = param.getDayaInstant();
			String tarifIndex = param.getTarifIndex();
			String statusTamper = param.getStatusTamper();
			//String totalOff = param.getTotalOff();
			String prediksiKreditHabis = param.getPrediksiKreditHabis();
			Integer paymentModeMeterType= Integer.parseInt(param.getPaymentModeMeterType());
			List<String> sudutIvr = getParts(param.getSudutIV(),4);
			String sudutI = sudutIvr.get(0);
			String sudutV = sudutIvr.get(1);
			String sudutR = sudutIvr.get(2);
			String firmware = param.getFirmware();
			
			MapTbl mapTbl = mapTblSvc.findByMeterAndMsisdn(meterId, msisdn);
			
			// lyd
			trxSvc.updateTransactionResponse(txId);
			Transaction trx = trxSvc.getTransactionByTrxId(txId);
			Timestamp timeStamp = trx.getResponseTime();
			
			DmTbl dmTbl = new DmTbl( balanceKWH, totalUsage, voltageR, voltageS, voltageT, arusR, arusS, arusT, powerFactor, dayaInstant, tarifIndex, statusTamper,/* totalOff, */prediksiKreditHabis, paymentModeMeterType, sudutI, sudutV, sudutR, firmware, timeStamp, mapTbl);
			if(txId.contains("s")){
				dmTbl.setTipeReading(ConstantValues.READING_TYPE_PERIODIC.getCode());			
			}else{
				dmTbl.setTipeReading(ConstantValues.READING_TYPE_REQUEST.getCode());
			}
			dmTblSvc.saveOrUpdate(dmTbl);

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			if(dmTbl.getTipeReading()==ConstantValues.READING_TYPE_REQUEST.getCode() ){
				nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
				nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
				nameValuePairs.add(HTTPValues.BALANCE_KWH.getNameValuePair(balanceKWH));
				nameValuePairs.add(HTTPValues.TOTAL_USAGE.getNameValuePair(totalUsage));
				nameValuePairs.add(HTTPValues.VOLTAGE_R.getNameValuePair(voltageR));
				nameValuePairs.add(HTTPValues.VOLTAGE_S.getNameValuePair(voltageS));
				nameValuePairs.add(HTTPValues.VOLTAGE_T.getNameValuePair(voltageT));
				nameValuePairs.add(HTTPValues.ARUS_R.getNameValuePair(arusR));
				nameValuePairs.add(HTTPValues.ARUS_S.getNameValuePair(arusS));
				nameValuePairs.add(HTTPValues.ARUS_T.getNameValuePair(arusT));
				nameValuePairs.add(HTTPValues.POWER_FACTOR.getNameValuePair(powerFactor));
				nameValuePairs.add(HTTPValues.DAYA_INSTANT.getNameValuePair(dayaInstant));
				nameValuePairs.add(HTTPValues.TARIF_INDEX.getNameValuePair(tarifIndex));
				nameValuePairs.add(HTTPValues.STATUS_TAMPER.getNameValuePair(statusTamper));
				//nameValuePairs.add(HTTPValues.TOTAL_OFF.getNameValuePair(totalOff));
				nameValuePairs.add(HTTPValues.PREDIKSI_KREDIT_HABIS.getNameValuePair(prediksiKreditHabis));
				nameValuePairs.add(HTTPValues.PAYMENT_MODE_METER_TYPE.getNameValuePair(paymentModeMeterType));
				nameValuePairs.add(HTTPValues.SUDUT_I.getNameValuePair(sudutI));
				nameValuePairs.add(HTTPValues.SUDUT_V.getNameValuePair(sudutV));
				nameValuePairs.add(HTTPValues.SUDUT_R.getNameValuePair(sudutR));
				nameValuePairs.add(HTTPValues.FIRMWARE.getNameValuePair(firmware));
				nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
				nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
				
				String url = UrlList.MGT_AMR_REQUEST.getUrl();
				String response = httpRequestPost(url, nameValuePairs);
				System.out.println("Response from MGT: "+response);
				
			}
			return responseResult(HTTPValues.TYPE_METER_DATA_RESP.getName(), "1", txId.toString());	
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_METER_DATA_RESP.getName(), "0", txId.toString());
		}
	}
	
	/**
	 * REQUEST LIMIT KREDIT METHOD
	 * this will receive any change regarding limit kredit and alarm data request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLimKredit
	 */
	@RequestMapping("/request-limkredit")
	public @ResponseBody String requestLimKredit(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String limKredit = req.getParameter(HTTPValues.LIM_KREDIT.getName());
		String setAlarm = req.getParameter(HTTPValues.SET_ALARM.getName());
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl updateMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = updateMeter.getMsisdn();
		Integer mapTblId = updateMeter.getMapId();
		LimTbl limTbl = new LimTbl(txId, limKredit, setAlarm, mapTblId);
		limTblSvc.saveOrUpdate(limTbl);
		
		Parameter param = new Parameter(txId, ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId, limKredit, setAlarm);
		param.setUtilityCode(ConstantValues.CC_LIM_KREDIT.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_SET_CL.getName(), param);
		String xml = parseTlkmTselToXML(tselXmlObj);
		String url = UrlList.USSD_LIMKREDIT_REQUEST.getUrl();
		
		String responseText = httpRequestPost(url,xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, updateMeter.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
		
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_SET_CL_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}

	/**
	 * RESPONSE LIMIT KREDIT METHOD
	 * this will be called when an request lim kredit sent from USSD, based on the related request that has been sent
	 * this will send a request call to MGT sending all data from USSD
	 * save table ..?
	 */
	public String responseLimKredit(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		try{
			String msisdn = param.getMeterNumber();
			String meterId = param.getMeterID();
			String limKredit = param.getLimitKredit();
			String setAlarm = param.getPengulanganAlarm();

			// lyd
			trxSvc.updateTransactionResponse(txId);
			Transaction trx = trxSvc.getTransactionByTrxId(txId);
			Timestamp timeStamp = trx.getResponseTime();
						
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
			nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
			nameValuePairs.add(HTTPValues.LIM_KREDIT.getNameValuePair(limKredit));
			nameValuePairs.add(HTTPValues.SET_ALARM.getNameValuePair(setAlarm));
			nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
			nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
			
			String url = UrlList.MGT_LIM_KREDIT_REQUEST.getUrl();
			
			String response = httpRequestPost(url,nameValuePairs);
			System.out.println("Response from MGT: "+response);

			return responseResult(HTTPValues.TYPE_CREDIT_LIMIT_RESULT_RESP.getName(), "1", txId.toString());
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_CREDIT_LIMIT_RESULT_RESP.getName(), "0", txId.toString());
		}
	}
	
	/**
	 * This is for alert testing purpose only
	 * @param req
	 * @return
	 */
	@RequestMapping("/request-alert")
	public @ResponseBody String requestAlert(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName()) ;
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId, ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setStatusTamper(req.getParameter(HTTPValues.STATUS_TAMPER.getName()));
		param.setAlertLBKWH(req.getParameter(HTTPValues.ALERT_LIM_BALANCE.getName()));
		param.setAlertType(req.getParameter(HTTPValues.TIPE_ALERT.getName()));
		param.setPowerStatus(req.getParameter(HTTPValues.POWER_STATUS.getName()));
		param.setAlertIT(req.getParameter(HTTPValues.ALERT_ISI_TOKEN.getName()));
		param.setTokenNumber(req.getParameter(HTTPValues.NO_TOKEN.getName()));
		param.setNilaiToken(req.getParameter(HTTPValues.NILAI_TOKEN.getName()));
		param.setBalanceKWH("3KWH");
		
		TselTlkm tselTlkm = new TselTlkm(HTTPValues.TYPE_ALERT.getName() , param);
		String xml = parseTselTlkmToXML(tselTlkm);
		String url = "http://"+req.getParameter("localIpPort")+"/Integration/";
		
		String responseText = httpRequestPost(url, xml);
		
		return responseText;
	}
	
	/**
	 * RESPONSE ALERT METHOD
	 * this will be called when an alert sent from USSD
	 * this will send a request call to MGT sending all data from USSD
	 * this will also insert the data of the data meter table [DM_TBL]
	 */
	public String responseAlert(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		try{
			String msisdn = param.getMeterNumber();
			String meterId = param.getMeterID();
			
			String statusTamper = param.getStatusTamper();
			String alertLimBalanceKWH = param.getAlertLBKWH();
			String alertIsiToken = param.getAlertIT();
			String nomorToken = param.getTokenNumber();
			String nilaiToken = param.getNilaiToken();
			String balanceKWH = param.getBalanceKWH();
			String typeAlert = param.getAlertType();
			String powerStatus = param.getPowerStatus();
			
			Integer tipeReading = ConstantValues.READING_TYPE_ALARM.getCode();
			MapTbl mapTbl = mapTblSvc.findByMeterAndMsisdn(meterId, msisdn);
			
			Calendar c = Calendar.getInstance();
			Timestamp timeStamp = new Timestamp(c.getTimeInMillis());
			
			DmTbl dmTbl = new DmTbl(balanceKWH, statusTamper, timeStamp, tipeReading, alertLimBalanceKWH, alertIsiToken, nomorToken, nilaiToken, typeAlert, powerStatus, mapTbl);
			dmTblSvc.saveOrUpdate(dmTbl);
			
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
			nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
			nameValuePairs.add(HTTPValues.STATUS_TAMPER.getNameValuePair(statusTamper));
			nameValuePairs.add(HTTPValues.ALERT_LIM_BALANCE.getNameValuePair(alertLimBalanceKWH));
			nameValuePairs.add(HTTPValues.ALERT_ISI_TOKEN.getNameValuePair(alertIsiToken));
			nameValuePairs.add(HTTPValues.NO_TOKEN.getNameValuePair(nomorToken));
			nameValuePairs.add(HTTPValues.NILAI_TOKEN.getNameValuePair(nilaiToken));
			nameValuePairs.add(HTTPValues.BALANCE_KWH.getNameValuePair(balanceKWH));
			nameValuePairs.add(HTTPValues.TIPE_ALERT.getNameValuePair(typeAlert));
			nameValuePairs.add(HTTPValues.POWER_STATUS.getNameValuePair(powerStatus));
			nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
			nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
			
			String url = UrlList.MGT_ALARM_REQUEST.getUrl();
			 	
			String response = httpRequestPost(url, nameValuePairs);
			System.out.println("Response from MGT: "+response);
			
			return responseResult(HTTPValues.TYPE_ALERT_RESP.getName(), "1", txId.toString());
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_ALERT_RESP.getName(), "0", txId.toString());
		}
	}

	
	/**
	 * REQUEST HISTORY TOKEN METHOD
	 * this will receive any historical token request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseHisToken
	 */
	@RequestMapping("/request-histoken")
	public @ResponseBody String requestHisToken(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName() );;
		
		MapTbl updateMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = updateMeter.getMsisdn();
		
		Parameter param = new Parameter(txId,ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_HISTORY_TOKEN.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_TOKEN_HIST.getName(), param);
		String xml = parseTlkmTselToXML(tselXmlObj);
		String url = UrlList.USSD_HISTOKEN_REQUEST.getUrl();
		String responseText = httpRequestPost(url,xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, updateMeter.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_TOKEN_HIST_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}

	/**
	 * RESPONSE HISTORY TOKEN METHOD
	 * this will be called when a request of response history token sent from USSD, based on the related request that has been sent
	 * this will send a request call to MGT sending all data from USSD
	 * save table ..?
	 */
	public String responseHisToken(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		try{
			String msisdn = param.getMeterNumber();
			String meterId = param.getMeterID();
			String nomorToken1to5 = param.getToken1to5(); // TOKEN : 20 digit each
			List<String> listToken = getParts(nomorToken1to5,20);
						
			// lyd
			trxSvc.updateTransactionResponse(txId);
			Transaction trx = trxSvc.getTransactionByTrxId(txId);
			Timestamp timeStamp = trx.getResponseTime();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
			nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
			nameValuePairs.addAll(HTTPValues.TOKEN_ARR.getNameValuePair(listToken));
			nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
			nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
			
			String url = UrlList.MGT_HISTOKEN_REQUEST.getUrl();			
			String response = httpRequestPost(url,nameValuePairs);
			System.out.println("Response from MGT: "+response);

			return responseResult(HTTPValues.TYPE_TOKEN_HIST_DATA_RESP.getName(), "1", txId.toString());
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_TOKEN_HIST_DATA_RESP.getName(), "0", txId.toString());
		}
	}
	

	/**
	 * REQUEST BILLING HISTORY METHOD
	 * this will receive any historical billing request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseBilHistory
	 */
	@RequestMapping("/request-bilhistory")
	public @ResponseBody String requestBilHistory(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName() );
		
		MapTbl updateMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = updateMeter.getMsisdn();
		
		Parameter param = new Parameter(txId,ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_BILLING_HISTORY.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_BILLING_HIST.getName(), param);
		String xml = parseTlkmTselToXML(tselXmlObj);
		String url = UrlList.USSD_HISTOKEN_REQUEST.getUrl();
		String responseText = httpRequestPost(url,xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, updateMeter.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_BILLING_HIST_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}

	/**
	 * RESPONSE LIMIT KREDIT METHOD
	 * this will be called when a request of response history token sent from USSD, based on the related request that has been sent
	 * this will send a request call to MGT sending all data from USSD
	 * save table ..?
	 */
	public String responseBilHistory(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		try{
			String msisdn = param.getMeterNumber();
			String meterId = param.getMeterID();
			String netEle1to5 = param.getNe1to5(); // NET EL CONSUMPTION 9 EACH
			String recPow1to5 = param.getRp1to5(); // NET EL CONSUMPTION 9 EACH
			List<String> netEle1to5list = getParts(netEle1to5, 9);
			List<String> recPow1to5list = getParts(recPow1to5, 9);
			
			// lyd
			trxSvc.updateTransactionResponse(txId);
			Transaction trx = trxSvc.getTransactionByTrxId(txId);
			Timestamp timeStamp = trx.getResponseTime();
			
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
			nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
			nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
			nameValuePairs.addAll(HTTPValues.NET_ELECTRICITY_CONSUMPTION_ARR.getNameValuePair(netEle1to5list));
			nameValuePairs.addAll(HTTPValues.RECHARGE_POWER_CONSUMPTION_ARR.getNameValuePair(recPow1to5list));
			nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));

			String url = UrlList.MGT_BILHISTORY_REQUEST.getUrl();		
			String response = httpRequestPost(url,nameValuePairs);
			System.out.println("Response from MGT: "+response);

			return responseResult(HTTPValues.TYPE_BILLING_HIST_DATA_RESP.getName(), "1", txId.toString());
		}catch (NumberFormatException nfe){
			logger.error(nfe.getMessage());
			return responseResult(HTTPValues.TYPE_BILLING_HIST_DATA_RESP.getName(), "0", txId.toString());
		}
	}

	
	// POST PAID =======================================================================================================
		

	/**
	 * RESPONSE METER PP METHOD
	 * REQUEST METER POST PAID, MERGE IN PRE PAID
	 * this will be called when a requestMeter with PP parameter call from USSD, related from the request meter that have been sent
	 * this will send a request call to MGT sending all data from USSD
	 * this will also insert the data of the data meter PP table [DM_TBL_PP]
	 */
	public String responseAMRPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();
				
		
//		// SUBSTRING begin index mulai dari 0, sedangkan end index mulai dari 1
//		
//		// GET HEXA EACH AMR	
//		String untilData13 = hexa.substring(0, 286); // total 286 digit
//		List<String> listHexaUntilData13 = getParts(untilData13,22); // 22 each
//		
//		String untilData22 = hexa.substring(286, 520); // total 234 digit : 286+234=520
//		List<String> listHexaUntilData22 = getParts(untilData22,26); // 26 each
//		
//		String untilData23 = hexa.substring(520, 540); // total 20 digit : 520+20=540
//		List<String> listHexaUntilData23 = getParts(untilData23,20); // 20 each
//		
//		String untilData34 = hexa.substring(540, 826); // total 286 digit : 540+286=826
//		List<String> listHexaUntilData34 = getParts(untilData34,26); // 26 each
//		
//		String untilData49 = hexa.substring(826, 1396); // total 570 digit : 826+570=1396
//		List<String> listHexaUntilData49 = getParts(untilData49,38); // 38 each
//		
//		
//		
//		// PARSE HEXA MESSAGE AMR	
//		
//		// hexa until data 13
//		String voltageR = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(0).substring(16, 20))))/100.0);
//		String voltageS = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(1).substring(16, 20))))/100.0);
//		String voltageT = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(2).substring(16, 20))))/100.0);
//		
//		String currentR = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(3).substring(16, 20))))/1000.0);
//		String currentS = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(4).substring(16, 20))))/1000.0);
//		String currentT = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(5).substring(16, 20))))/1000.0);
//	
//		String powerFactorR = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(6).substring(16, 20))))/1000.0);
//		String powerFactorS = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(7).substring(16, 20))))/1000.0);
//		String powerFactorT = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(8).substring(16, 20))))/1000.0);
//		
//		String phaseAngelR = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(9).substring(16, 20))))/10.0);
//		String phaseAngelS = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(10).substring(16, 20))))/10.0);
//		String phaseAngelT = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(11).substring(16, 20))))/10.0);
//		
//		String frequency = "" + (((double)(parseHexaToDecimal(listHexaUntilData13.get(12).substring(16, 20))))/100.0);
//		
//		// hexa until data 22
//		String activePowerR = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(0).substring(16, 24))))/10.0);
//		String activePowerS = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(1).substring(16, 24))))/10.0);
//		String activePowerT = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(2).substring(16, 24))))/10.0);
//		
//		String reactivePowerR = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(3).substring(16, 24))))/10.0);
//		String reactivePowerS = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(4).substring(16, 24))))/10.0);
//		String reactivePowerT = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(5).substring(16, 24))))/10.0);
//		
//		String apparentPowerR = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(6).substring(16, 24))))/10.0);
//		String apparentPowerS = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(7).substring(16, 24))))/10.0);
//		String apparentPowerT = "" + (((double)(parseHexaToDecimal(listHexaUntilData22.get(8).substring(16, 24))))/10.0);
//		
//		// hexa until data 23
//		String statusOutputDevice = "" + (parseHexaToDecimal(listHexaUntilData23.get(0).substring(16, 18)));
//		
//		// hexa until data 34
//		String totalEnergyApparent = "" + (parseHexaToDecimal(listHexaUntilData34.get(0).substring(16, 24)));
//		
//		String totalEnergyActive = "" + (parseHexaToDecimal(listHexaUntilData34.get(1).substring(16, 24)));
//		String totalEnergyActiveTarrif1 = "" + (parseHexaToDecimal(listHexaUntilData34.get(2).substring(16, 24)));
//		String totalEnergyActiveTarrif2 = "" + (parseHexaToDecimal(listHexaUntilData34.get(3).substring(16, 24)));
//		String totalEnergyActiveTarrif3 = "" + (parseHexaToDecimal(listHexaUntilData34.get(4).substring(16, 24)));
//		String totalEnergyActiveTarrif4 = "" + (parseHexaToDecimal(listHexaUntilData34.get(5).substring(16, 24)));
//		
//		String totalEnergyReactive = "" + (parseHexaToDecimal(listHexaUntilData34.get(6).substring(16, 24)));
//		String totalEnergyReactiveTarrif1 = "" + (parseHexaToDecimal(listHexaUntilData34.get(7).substring(16, 24)));
//		String totalEnergyReactiveTarrif2 = "" + (parseHexaToDecimal(listHexaUntilData34.get(8).substring(16, 24)));
//		String totalEnergyReactiveTarrif3 = "" + (parseHexaToDecimal(listHexaUntilData34.get(9).substring(16, 24)));
//		String totalEnergyReactiveTarrif4 = "" + (parseHexaToDecimal(listHexaUntilData34.get(10).substring(16, 24)));
//		
//		// hexa until data 49
//		String activeMaxDemandTotal = "" + (parseHexaToDecimal(listHexaUntilData49.get(0).substring(18, 24))) + " - " + (listHexaUntilData49.get(0).substring(24, 36));
//		String activeMaxDemandTarrif1 = "" + (parseHexaToDecimal(listHexaUntilData49.get(1).substring(18, 24))) + " - " + (listHexaUntilData49.get(1).substring(24, 36));
//		String activeMaxDemandTarrif2 = "" + (parseHexaToDecimal(listHexaUntilData49.get(2).substring(18, 24))) + " - " + (listHexaUntilData49.get(2).substring(24, 36));
//		String activeMaxDemandTarrif3 = "" + (parseHexaToDecimal(listHexaUntilData49.get(3).substring(18, 24))) + " - " + (listHexaUntilData49.get(3).substring(24, 36));
//		String activeMaxDemandTarrif4 = "" + (parseHexaToDecimal(listHexaUntilData49.get(4).substring(18, 24))) + " - " + (listHexaUntilData49.get(4).substring(24, 36));
//				
//		String reactiveMaxDemandTotal = "" + (parseHexaToDecimal(listHexaUntilData49.get(5).substring(18, 24))) + " - " + (listHexaUntilData49.get(5).substring(24, 36));
//		String reactiveMaxDemandTarrif1 = "" + (parseHexaToDecimal(listHexaUntilData49.get(6).substring(18, 24))) + " - " + (listHexaUntilData49.get(6).substring(24, 36));
//		String reactiveMaxDemandTarrif2 = "" + (parseHexaToDecimal(listHexaUntilData49.get(7).substring(18, 24))) + " - " + (listHexaUntilData49.get(7).substring(24, 36));
//		String reactiveMaxDemandTarrif3 = "" + (parseHexaToDecimal(listHexaUntilData49.get(8).substring(18, 24))) + " - " + (listHexaUntilData49.get(8).substring(24, 36));
//		String reactiveMaxDemandTarrif4 = "" + (parseHexaToDecimal(listHexaUntilData49.get(9).substring(18, 24))) + " - " + (listHexaUntilData49.get(9).substring(24, 36));
//			
//		String apparentMaxDemandTotal = "" + (parseHexaToDecimal(listHexaUntilData49.get(10).substring(18, 24))) + " - " + (listHexaUntilData49.get(10).substring(24, 36));
//		String apparentMaxDemandTarrif1 = "" + (parseHexaToDecimal(listHexaUntilData49.get(11).substring(18, 24))) + " - " + (listHexaUntilData49.get(11).substring(24, 36));
//		String apparentMaxDemandTarrif2 = "" + (parseHexaToDecimal(listHexaUntilData49.get(12).substring(18, 24))) + " - " + (listHexaUntilData49.get(12).substring(24, 36));
//		String apparentMaxDemandTarrif3 = "" + (parseHexaToDecimal(listHexaUntilData49.get(13).substring(18, 24))) + " - " + (listHexaUntilData49.get(13).substring(24, 36));
//		String apparentMaxDemandTarrif4 = "" + (parseHexaToDecimal(listHexaUntilData49.get(14).substring(18, 24))) + " - " + (listHexaUntilData49.get(14).substring(24, 36));
//			
		
		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
					
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
//		// HEXA MESSAGE
//		nameValuePairs.add(HTTPValues.VOLTAGE_R.getNameValuePair(voltageR));
//		nameValuePairs.add(HTTPValues.VOLTAGE_S.getNameValuePair(voltageS));
//		nameValuePairs.add(HTTPValues.VOLTAGE_T.getNameValuePair(voltageT));
//		nameValuePairs.add(HTTPValues.CURRENT_R.getNameValuePair(currentR));
//		nameValuePairs.add(HTTPValues.CURRENT_S.getNameValuePair(currentS));
//		nameValuePairs.add(HTTPValues.CURRENT_T.getNameValuePair(currentT));
//		nameValuePairs.add(HTTPValues.POWER_FACTOR_R.getNameValuePair(powerFactorR));
//		nameValuePairs.add(HTTPValues.POWER_FACTOR_S.getNameValuePair(powerFactorS));
//		nameValuePairs.add(HTTPValues.POWER_FACTOR_T.getNameValuePair(powerFactorT));
//		nameValuePairs.add(HTTPValues.PHASE_ANGEL_R.getNameValuePair(phaseAngelR));
//		nameValuePairs.add(HTTPValues.PHASE_ANGEL_S.getNameValuePair(phaseAngelS));
//		nameValuePairs.add(HTTPValues.PHASE_ANGEL_T.getNameValuePair(phaseAngelT));
//		nameValuePairs.add(HTTPValues.FREQUENCY.getNameValuePair(frequency));
//		
//		nameValuePairs.add(HTTPValues.ACTIVE_POWER_R.getNameValuePair(activePowerR));
//		nameValuePairs.add(HTTPValues.ACTIVE_POWER_S.getNameValuePair(activePowerS));
//		nameValuePairs.add(HTTPValues.ACTIVE_POWER_T.getNameValuePair(activePowerT));
//		nameValuePairs.add(HTTPValues.REACTIVE_POWER_R.getNameValuePair(reactivePowerR));
//		nameValuePairs.add(HTTPValues.REACTIVE_POWER_S.getNameValuePair(reactivePowerS));
//		nameValuePairs.add(HTTPValues.REACTIVE_POWER_T.getNameValuePair(reactivePowerT));
//		nameValuePairs.add(HTTPValues.APPARENT_POWER_R.getNameValuePair(apparentPowerR));
//		nameValuePairs.add(HTTPValues.APPARENT_POWER_S.getNameValuePair(apparentPowerS));
//		nameValuePairs.add(HTTPValues.APPARENT_POWER_T.getNameValuePair(apparentPowerT));
//		
//		nameValuePairs.add(HTTPValues.STATUS_OUTPUT_DEVICE.getNameValuePair(statusOutputDevice));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_APPARENT.getNameValuePair(totalEnergyApparent));
//		
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_ACTIVE.getNameValuePair(totalEnergyActive));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_ACTIVE_TARRIF1.getNameValuePair(totalEnergyActiveTarrif1));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_ACTIVE_TARRIF2.getNameValuePair(totalEnergyActiveTarrif2));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_ACTIVE_TARRIF3.getNameValuePair(totalEnergyActiveTarrif3));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_ACTIVE_TARRIF4.getNameValuePair(totalEnergyActiveTarrif4));
//		
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_REACTIVE.getNameValuePair(totalEnergyReactive));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_REACTIVE_TARRIF1.getNameValuePair(totalEnergyReactiveTarrif1));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_REACTIVE_TARRIF2.getNameValuePair(totalEnergyReactiveTarrif2));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_REACTIVE_TARRIF3.getNameValuePair(totalEnergyReactiveTarrif3));
//		nameValuePairs.add(HTTPValues.TOTAL_ENERGY_REACTIVE_TARRIF4.getNameValuePair(totalEnergyReactiveTarrif4));
//		
//		nameValuePairs.add(HTTPValues.ACTIVE_MAX_DEMAND_TOTAL.getNameValuePair(activeMaxDemandTotal));
//		nameValuePairs.add(HTTPValues.ACTIVE_MAX_DEMAND_TARRIF1.getNameValuePair(activeMaxDemandTarrif1));
//		nameValuePairs.add(HTTPValues.ACTIVE_MAX_DEMAND_TARRIF2.getNameValuePair(activeMaxDemandTarrif2));
//		nameValuePairs.add(HTTPValues.ACTIVE_MAX_DEMAND_TARRIF3.getNameValuePair(activeMaxDemandTarrif3));
//		nameValuePairs.add(HTTPValues.ACTIVE_MAX_DEMAND_TARRIF4.getNameValuePair(activeMaxDemandTarrif4));
//		
//		nameValuePairs.add(HTTPValues.REACTIVE_MAX_DEMAND_TOTAL.getNameValuePair(reactiveMaxDemandTotal));
//		nameValuePairs.add(HTTPValues.REACTIVE_MAX_DEMAND_TARRIF1.getNameValuePair(reactiveMaxDemandTarrif1));
//		nameValuePairs.add(HTTPValues.REACTIVE_MAX_DEMAND_TARRIF2.getNameValuePair(reactiveMaxDemandTarrif2));
//		nameValuePairs.add(HTTPValues.REACTIVE_MAX_DEMAND_TARRIF3.getNameValuePair(reactiveMaxDemandTarrif3));
//		nameValuePairs.add(HTTPValues.REACTIVE_MAX_DEMAND_TARRIF4.getNameValuePair(reactiveMaxDemandTarrif4));
//		
//		nameValuePairs.add(HTTPValues.APPARENT_MAX_DEMAND_TOTAL.getNameValuePair(apparentMaxDemandTotal));
//		nameValuePairs.add(HTTPValues.APPARENT_MAX_DEMAND_TARRIF1.getNameValuePair(apparentMaxDemandTarrif1));
//		nameValuePairs.add(HTTPValues.APPARENT_MAX_DEMAND_TARRIF2.getNameValuePair(apparentMaxDemandTarrif2));
//		nameValuePairs.add(HTTPValues.APPARENT_MAX_DEMAND_TARRIF3.getNameValuePair(apparentMaxDemandTarrif3));
//		nameValuePairs.add(HTTPValues.APPARENT_MAX_DEMAND_TARRIF4.getNameValuePair(apparentMaxDemandTarrif4));
		
		String url = UrlList.MGT_AMR_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_METER_READING_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST LOAD PROFILE METHOD
	 * this will receive any load profile request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-loadprofilepp")
	public @ResponseBody String requestLoadProfilePP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Load Profile can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_LOAD_PROFILE_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_LOAD_PROFILE_PP.getName(),param);
		String url = UrlList.USSD_LOAD_PROFILE_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_LOAD_PROFILE_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseLoadProfilePP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();
		
		// TO DO PARSE HEXA MESSAGE LOAD PROFILE PP

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_LOAD_PROFILE_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_LOAD_PROFILE_PP_RESP.getName(), "1",txId);
	}
	

	/**
	 * REQUEST EVENT LOG METHOD
	 * this will receive any event log request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-eventlogpp")
	public @ResponseBody String requestEventLogPP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Event Log can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_EVENT_LOG_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_EVENT_LOG_PP.getName(),param);
		String url = UrlList.USSD_EVENT_LOG_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_EVENT_LOG_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseEventLogPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();
		
		// TO DO PARSE HEXA MESSAGE EVENT LOG

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_EVENT_LOG_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_EVENT_LOG_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST BILLING METHOD
	 * this will receive any billing request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseBillingPP
	 */
	@RequestMapping("/request-billingpp")
	public @ResponseBody String requestBillingPP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName()) ;
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Billing can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_BILLING_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_BILLING_PP.getName(),param);
		String url = UrlList.USSD_BILLING_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_BILLING_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseBillingPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();
		
		// TO DO PARSE HEXA MESSAGE BILLING PP

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
		
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_BILLING_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_BILLING_PP_RESP.getName(), "1",txId);
	}
	
	
	/**
	 * This is for alarm testing purpose only
	 * @param req
	 * @return
	 */
	@RequestMapping("/request-alarmpp")
	public @ResponseBody String requestAlarmPP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName()) ;
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		String msisdn = requestedMetr.getMsisdn();
		
		// lyd
		Parameter param = new Parameter(txId, ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_ALARM_PP.getPLNCode());
		param.setHexaMsg(req.getParameter(HTTPValues.HEXA_MSG.getName()));
		
		TselTlkm tselTlkm = new TselTlkm(HTTPValues.TYPE_ALARM_PP.getName() , param);
		String xml = parseTselTlkmToXML(tselTlkm);
		String url = "http://"+req.getParameter("localIpPort")+"/Integration/";
		
		String responseText = httpRequestPost(url, xml);
		
		return responseText;
	}

	public String responseAlarmPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();

		// TO DO PARSE HEXA MESSAGE ALARM

		Calendar c = Calendar.getInstance();
		Timestamp timeStamp = new Timestamp(c.getTimeInMillis());
		
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_ALARM_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_ALARM_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST RECALL LOAD PROFILE METHOD
	 * this will receive any event log request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-recallloadprofilepp")
	public @ResponseBody String requestRecallLoadProfilePP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Recall Load Profile can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_RECALL_LOAD_PROFILE_PP.getName(),param);
		String url = UrlList.USSD_RECALL_LOAD_PROFILE_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_RECALL_LOAD_PROFILE_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseRecallLoadProfilePP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();

		// TO DO PARSE HEXA MESSAGE RECALL LOAD PROFILE

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_RECALL_LOAD_PROFILE_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_RECALL_LOAD_PROFILE_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST TIME SYNC METHOD
	 * this will receive any event log request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-timesyncpp")
	public @ResponseBody String requestTimeSyncPP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Time Sync can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_TIME_SYNC_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_TIME_SYNC_PP.getName(),param);
		String url = UrlList.USSD_TIME_SYNC_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_TIME_SYNC_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseTimeSyncPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String status = param.getStatus();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		nameValuePairs.add(HTTPValues.STATUS.getNameValuePair(status));
		
		String url = UrlList.MGT_TIME_SYNC_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_TIME_SYNC_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST REMOTE METHOD
	 * this will receive any event log request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-remotepp")
	public @ResponseBody String requestRemotePP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		String remote = req.getParameter(HTTPValues.REMOTE.getName());
			
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Remote can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		Integer mapTblId = requestedMetr.getMapId();
		RemTbl remTbl = new RemTbl(txId, remote, mapTblId);
		remTblSvc.saveOrUpdate(remTbl);
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_REMOTE_PP.getPLNCode());
		param.setRemote(remote);
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_REMOTE_PP.getName(),param);
		String url = UrlList.USSD_REMOTE_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_REMOTE_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseRemotePP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();
		
		// TO DO PARSE HEXA MESSAGE REMOTE

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message
		
		String url = UrlList.MGT_REMOTE_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_REMOTE_PP_RESP.getName(), "1",txId);
	}
	
	/**
	 * REQUEST SCADA SYSTEM METHOD
	 * this will receive any event log request from MGT
	 * this response will give the 1/0 response from USSD
	 * the actual response data from this request will be a request call from USSD that will be received by responseLoadProfilePP
	 */
	@RequestMapping("/request-scadasystempp")
	public @ResponseBody String requestScadaSystemPP(HttpServletRequest req){
		
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String txId = req.getParameter(HTTPValues.TX_ID.getName());
		
		MapTbl requestedMetr = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		if(!requestedMetr.getTipePlg().equalsIgnoreCase("2"))return "Scada System can only used for post paid meter, "+meterId+" registered as Pre Paid";

		String msisdn = requestedMetr.getMsisdn();
		
		Parameter param = new Parameter(txId.toString(), ConstantValues.NO_AKSES.getCode().toString(), tipePu.toString(), msisdn, meterId);
		param.setUtilityCode(ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCode());
		
		TlkmTsel tselXmlObj = new TlkmTsel(HTTPValues.TYPE_SUBMIT_SCADA_SYSTEM_PP.getName(),param);
		String url = UrlList.USSD_SCADA_SYSTEM_PP_REQUEST.getUrl();
		
		String xml = parseTlkmTselToXML(tselXmlObj);
		String responseText = httpRequestPost(url, xml);
		
		// lyd
		trxSvc.saveNewTransaction(txId, requestedMetr.getMapId(), meterId, Integer.parseInt(param.getUtilityCode().toString()));
				
		txSemaphores.put(txId, new Semaphore(0));
		TselTlkm response = parseXMLtoTselTlkm(responseText);
		
		if(response!=null && response.getParam()!=null && HTTPValues.TYPE_SUBMIT_SCADA_SYSTEM_PP_RESP.equal(response.getType()) ){
			responseText = waitResponseTxStatus(txId);
			//responseText = response.getParam().getResponseStatus();
		}else{
			logger.error(response.toString());
			responseText = "-1";
		}
		clearWaitResponseVariable(txId);
		return responseText;
	}
	
	public String responseScadaSystemPP(Parameter param){
		
		String txId = param.getTrxId();
		//String txId = tId.substring(11);
		
		String hexa = param.getHexaMsg();
		String msisdn = param.getMeterNumber();
		String meterId = param.getMeterID();

		// TO DO PARSE HEXA MESSAGE SCADA SYSTEM

		// lyd
		trxSvc.updateTransactionResponse(txId);
		Transaction trx = trxSvc.getTransactionByTrxId(txId);
		Timestamp timeStamp = trx.getResponseTime();
				
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.MSISDN.getNameValuePair(msisdn));
		nameValuePairs.add(HTTPValues.METER_ID.getNameValuePair(meterId));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		nameValuePairs.add(HTTPValues.TIMESTAMP.getNameValuePair(timeStamp));
		// data" lainnya yg ada di dalem hexa message 
		
		String url = UrlList.MGT_SCADA_SYSTEM_PP_REQUEST.getUrl();
		String response = httpRequestPost(url, nameValuePairs);
		System.out.println("Response from MGT: "+response);
		
		return responseResult(HTTPValues.TYPE_SCADA_SYSTEM_PP_RESP.getName(), "1",txId);
	}
	
	// ETC ========================================================================================================
	
	@RequestMapping("/txStatus")
	public @ResponseBody String txStatus(HttpServletRequest req){
		
		String tId = req.getParameter("transId");
		String txId = tId.substring(11);
		
		String status = req.getParameter("status");
		String accessCode = ConstantValues.NO_AKSES.getCode().toString();
		int st = Integer.parseInt(status);
		
		Transaction tx = trxSvc.getTransactionByTrxId(txId);

		System.out.println("TXSTATUS RECEIVED tx id:"+txId+" status: "+status);

		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
		nameValuePairs.add(HTTPValues.NETWORK_STATUS.getNameValuePair(st));
		nameValuePairs.add(HTTPValues.TX_ID.getNameValuePair(txId));
		
		if(st == 0 || st == 27){
			
			Semaphore txSem = txSemaphores.get(txId);
			if(txSem!=null){
				txStatus.put(txId, status);
				txSem.release();
			}
			
			trxSvc.updateTransactionSuccessFailStatus(txId,st);
			
			String url = UrlList.MGT_NETWORK_STATUS.getUrl();
			
//			if(tx.getType() == ConstantValues.CC_AMR.getPLNCodeInt()){
//				url = UrlList.MGT_AMR_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_TOKEN_REQUEST.getPLNCodeInt()){
//				url = UrlList.MGT_TOKEN_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_LIM_KREDIT.getPLNCodeInt()){
//				url = UrlList.MGT_LIM_KREDIT_REQUEST.getUrl();
//			} 
//			else if(tx.getType() == ConstantValues.CC_HISTORY_TOKEN.getPLNCodeInt()){
//				url = UrlList.MGT_HISTOKEN_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_BILLING_HISTORY.getPLNCodeInt()){
//				url = UrlList.MGT_BILHISTORY_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_AMR_PP.getPLNCodeInt()){
//				url = UrlList.MGT_AMR_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_LOAD_PROFILE_PP.getPLNCodeInt()){
//				url = UrlList.MGT_LOAD_PROFILE_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_EVENT_LOG_PP.getPLNCodeInt()){
//				url = UrlList.MGT_EVENT_LOG_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_BILLING_PP.getPLNCodeInt()){
//				url = UrlList.MGT_BILLING_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCodeInt()){
//				url = UrlList.MGT_RECALL_LOAD_PROFILE_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_TIME_SYNC_PP.getPLNCodeInt()){
//				url = UrlList.MGT_TIME_SYNC_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_REMOTE_PP.getPLNCodeInt()){
//				url = UrlList.MGT_REMOTE_PP_REQUEST.getUrl();
//			}
//			else if(tx.getType() == ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCodeInt()){
//				url = UrlList.MGT_SCADA_SYSTEM_PP_REQUEST.getUrl();
//			}
			
			String response = httpRequestPost(url, nameValuePairs);
			System.out.println("Response from MGT: "+response);
			
		}else if(st == 34 || st ==72){
			
			int retTime = st==34? 120000:40000; //34 : 2min, 72 : 40sec
			if(tx.getRetry()<2){
				MapTbl meter = mapTblSvc.findById(tx.getMeter().getMapId());			
				String tipePu = meter.getTipePu().toString();
				String msisdn = meter.getMsisdn();
				String meterId = meter.getMeterId();
				
				String url = UrlList.MGT_NETWORK_STATUS.getUrl();
				try{
					if(tx.getType() == ConstantValues.CC_AMR.getPLNCodeInt()){
						//url = UrlList.MGT_AMR_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_AMR.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_AMR.getCode(), retTime )).start();
					}else if(tx.getType() == ConstantValues.CC_TOKEN_REQUEST.getPLNCodeInt()){
						//url = UrlList.MGT_TOKEN_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						TxTbl token = txTblSvc.findById(txId);
						String tokenNumber = token.getToken();
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId, tokenNumber);
						param.setUtilityCode(ConstantValues.CC_TOKEN_REQUEST.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_TOKEN_REQUEST.getCode(), retTime )).start();
					}else if(tx.getType() == ConstantValues.CC_LIM_KREDIT.getPLNCodeInt()){
						//url = UrlList.MGT_LIM_KREDIT_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						LimTbl limit = limTblSvc.findById(txId);
						String limitKredit = limit.getLimitKredit();
						String setAlarm = limit.getSetAlarm();
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId, limitKredit, setAlarm);
						param.setUtilityCode(ConstantValues.CC_LIM_KREDIT.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_LIM_KREDIT.getCode(), retTime )).start();
					} else if(tx.getType() == ConstantValues.CC_HISTORY_TOKEN.getPLNCodeInt()){
						//url = UrlList.MGT_HISTOKEN_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_HISTORY_TOKEN.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_HISTORY_TOKEN.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_BILLING_HISTORY.getPLNCodeInt()){
						//url = UrlList.MGT_BILHISTORY_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_BILLING_HISTORY.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_BILLING_HISTORY.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_AMR_PP.getPLNCodeInt()){
						//url = UrlList.MGT_AMR_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_AMR_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_AMR_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_LOAD_PROFILE_PP.getPLNCodeInt()){
						//url = UrlList.MGT_LOAD_PROFILE_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_LOAD_PROFILE_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_LOAD_PROFILE_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_EVENT_LOG_PP.getPLNCodeInt()){
						//url = UrlList.MGT_EVENT_LOG_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_EVENT_LOG_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_EVENT_LOG_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_BILLING_PP.getPLNCodeInt()){
						//url = UrlList.MGT_BILLING_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_BILLING_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_BILLING_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCodeInt()){
						//url = UrlList.MGT_RECALL_LOAD_PROFILE_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_RECALL_LOAD_PROFILE_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_TIME_SYNC_PP.getPLNCodeInt()){
						//url = UrlList.MGT_TIME_SYNC_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_TIME_SYNC_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_TIME_SYNC_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_REMOTE_PP.getPLNCodeInt()){
						//url = UrlList.MGT_REMOTE_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						RemTbl remote = remTblSvc.findById(txId);
						String rem = remote.getRemote();
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_REMOTE_PP.getPLNCode());
						param.setRemote(rem);
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_REMOTE_PP.getCode(), retTime )).start();
					}
					else if(tx.getType() == ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCodeInt()){
						//url = UrlList.MGT_SCADA_SYSTEM_PP_REQUEST.getUrl();
						String response = httpRequestPost(url, nameValuePairs);
						System.out.println("Response from MGT: "+response);
						
						Parameter param = new Parameter(txId, accessCode, tipePu, msisdn, meterId);
						param.setUtilityCode(ConstantValues.CC_SCADA_SYSTEM_PP.getPLNCode());
						
						System.out.println("Start refire thread");
						new Thread(new RequestThread(param, ConstantValues.CC_SCADA_SYSTEM_PP.getCode(), retTime )).start();
					}
					trxSvc.saveRetTransaction(txId, st);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			else {
				Semaphore txSem = txSemaphores.get(txId);
				if(txSem!=null){
					txStatus.put(txId, status);
					txSem.release();
				}
				
				trxSvc.updateTransactionSuccessFailStatus(txId,st);
			}
		}
		
		return "1";
	}
	
	/**
	 * SEND SMS METHOD
	 * forwarding sms to tsel
	 */
	@RequestMapping("/send-sms")
	public @ResponseBody String sendSms(HttpServletRequest req){
		String xml = getXMLFromRequest(req);
		String responseText = httpRequestPost(UrlList.USSD_SEND_SMS.getUrl(), xml);
		return responseText;
	}
	
	/**
	 * PAIRING METHOD
	 * this will save the meter data into the MapTbl 
	 * there is no further connection to USSD for this method
	 */
	@RequestMapping("/pair")
	public @ResponseBody String pair(HttpServletRequest req){
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String msisdn = req.getParameter(HTTPValues.MSISDN.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		String tipePlg = req.getParameter(HTTPValues.TIPE_PELANGGAN.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		
		MapTbl newMeter = new MapTbl(meterId, msisdn, tipeMeter, tipePlg, tipePu);
		newMeter.setInterval(86400000);
		MapTbl deletedMap = mapTblSvc.delete(msisdn, meterId);
		if(deletedMap!=null){
			jobSvc.stopJob(deletedMap.getMapId().toString());
			newMeter.setInterval(deletedMap.getInterval());
			newMeter.setMapId(deletedMap.getMapId());
		}
		mapTblSvc.saveOrUpdate(newMeter);		
		
		jobSvc.meterReadingJob(newMeter);
		
		System.out.println("Pair Complete");
		return "1";	
	}
	

	
	@RequestMapping("/test-connection")
	public @ResponseBody String test(HttpServletRequest req){
		String url = "http://202.3.208.77:9000/?";
		String xml = "<?xml version=\"1.0\"><test>Connection to Tsel</test>";
		String response = httpRequestPost(url, xml);
		
		logger.error("Response : "+response);
		
		return response;	
	}
	
	/**
	 * REQUEST JOB INTERVAL METHOD
	 * this will receive any job interval update request from MGT
	 * this response will give the 1/0 response from MD
	 * this will save the new interval, and reschedule it
	 */
	@RequestMapping("/request-newinterval")
	public @ResponseBody String requestNewInterval(HttpServletRequest req){
		String response ="";
		try{
			
			String meterId = req.getParameter(HTTPValues.METER_ID.getName());
			String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
			Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
			Integer interval = Integer.parseInt(req.getParameter(HTTPValues.ALERT_INTERVAL.getName()));
			
			MapTbl updateMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
			updateMeter.setInterval(interval);
			
			mapTblSvc.saveOrUpdate(updateMeter);
			if(interval==0){
				response = jobSvc.stopJob(updateMeter.getMapId().toString());
			}else{
				response =  jobSvc.updateMeterReadingSchedule(updateMeter);		
			}
		}catch(Exception e){
			System.out.println("Error in new interval");
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		
		return response;
	}
	
	/**
	 * REQUEST NEW SCHEDULE [BUKA KERAN]
	 * this will create a new schedule and open the 'keran' 
	 * the data will be sent periodically depend on the time
	 */
	@RequestMapping("/request-openkeran")
	public @ResponseBody String requestOpenKeran(HttpServletRequest req){
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		Integer interval = Integer.parseInt(req.getParameter(HTTPValues.KERAN_INTERVAL.getName()));
		String jobId = req.getParameter(HTTPValues.JOB_IDKERAN.getName());

		MapTbl meter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		return jobSvc.openKeran(meter, interval, jobId);
	}
	
	/**
	 * REQUEST SHUTDOWN SCHEDULE [TUTUP KERAN]
	 * this will closed an existing schedule that has been open
	 */
	@RequestMapping("/request-closekeran")
	public @ResponseBody String requestCloseKeran(HttpServletRequest req){
		String jobId = req.getParameter(HTTPValues.JOB_IDKERAN.getName());
		
		return jobSvc.closeKeran(jobId);
	}

	/**
	 * REQUEST DATA METER HISTORY
	 * this will query periodic data from DmTbl
	 */
	@RequestMapping("/request-meterhistory")
	public @ResponseBody String requestMeterHistory(HttpServletRequest req){
		String meterId = req.getParameter(HTTPValues.METER_ID.getName());
		String tipeMeter = req.getParameter(HTTPValues.TIPE_METER.getName());
		Integer tipePu = Integer.parseInt(req.getParameter(HTTPValues.TIPE_PU.getName()));
		String start = req.getParameter(HTTPValues.START_DATE.getName())+" 00:00:00 GMT+07:00";
		String end = req.getParameter(HTTPValues.END_DATE.getName()) +" 23:59:59 GMT+07:00";

		MapTbl findMeter = mapTblSvc.findByMeterAndType(meterId, tipeMeter, tipePu);
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
		Date dateStart=null;
		Date dateEnd=null;
		try {
			dateStart = sdf.parse(start);
			dateEnd = sdf.parse(end);
			
			System.out.println("\nGET FROM MGT: from: "+start+" to "+end);
			System.out.println("HISTORY METER REQUEST: from: "+dateStart+" to "+dateEnd);
			
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Timestamp st = new Timestamp(dateStart.getTime());
		Timestamp en = new Timestamp(dateEnd.getTime());

		System.out.println("HISTORY METER TO DB: from: "+st+" to "+en);
		
		List<DmTbl> result = dmTblSvc.findByRange(findMeter, st, en); 
		
		List <DmTbl> listDmTbl = new ArrayList<DmTbl>();
		for(DmTbl dm : result){
			DmTbl dmTbl = new DmTbl(dm.getBalanceKWH(), dm.getTotalUsage(), 
					dm.getVoltageR(), dm.getVoltageS(), dm.getVoltageT(), 
					dm.getArusR(), dm.getArusS(), dm.getArusT(), 
					dm.getPowerFactor(), dm.getDayaInstant(), dm.getTarifIndex(), 
					dm.getStatusTamper(), /*dm.getTotalOff(),*/ dm.getPrediksiKreditHabis(), 
					dm.getPaymentModeMeterType(), 
					dm.getSudutI(), dm.getSudutV(), dm.getSudutR(), dm.getFirmware(), dm.getTimeStamp().getTime());
			dmTbl.setTimeStamp(dm.getTimeStamp());
			listDmTbl.add(dmTbl);
		}
		
		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		
		String json = gson.toJson(listDmTbl);
		
		System.out.println("JSON: \n"+json);
		
		return json;
	}
	
	/**
	 * HTTP REQUEST POST METHOD
	 * this will send a request call to the url parameter with the xml as body
	 */
	private String httpRequestPost(String url, String xml){
		System.out.println("POST TO "+url+" XML : \n"+formatXML(xml));
		PostMethod post = new PostMethod(url);   
		String response = null;
	    try {
	    	
	        StringRequestEntity requestEntity = new StringRequestEntity(xml);
	        post.setRequestEntity(requestEntity);
	        
	        post.setRequestEntity(requestEntity);
	        post.setRequestHeader("Content-type",  "text/xml; charset=UTF-8");
	        org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
	        int result = httpclient.executeMethod(post);
	        
	        response = post.getResponseBodyAsString();
	        
	    } catch (IOException e) {
	        logger.error(e.getMessage());
	        return null;
	    } finally {
	        post.releaseConnection();
	    }
	    return response;
	}
	/**
	 * HTTP REQUEST POST METHOD
	 * this will send a request call to the url parameter with name value pair
	 */
	private String httpRequestPost(String url, List<NameValuePair> nameValuePairs){
		System.out.println("Post to: "+url+" TOTAL PARAM : "+nameValuePairs.size());
		for(NameValuePair nvp : nameValuePairs){
			System.out.println(nvp.getName()+"="+nvp.getValue());
		}
		
		HttpClient client = new DefaultHttpClient();
		HttpPost request = new HttpPost(url);
		String responseText;
		try{
			request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = client.execute(request);
	
			// Get the response
			StringBuilder respText= new StringBuilder();
			BufferedReader rd = new BufferedReader
			  (new InputStreamReader(response.getEntity().getContent()));
			    
			String line = "";
			while ((line = rd.readLine()) != null) {
				respText.append(line);
			}
			responseText = respText.toString();
		}catch(IOException ioe){
			ioe.printStackTrace();
			return "0";
		}
		
		return responseText;
	}
	

	public List<String> getParts(String string, int partitionSize) {
        List<String> parts = new ArrayList<String>();
        int len = string.length();
        for (int i=0; i<len; i+=partitionSize)
        {
            parts.add(string.substring(i, Math.min(len, i + partitionSize)));
        }
        return parts;
    }
	
	private String getXMLFromRequest(HttpServletRequest request){
		
		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			} else {
				stringBuilder.append("");
			}
		} catch (IOException ex) {
			logger.error(ex.getMessage());
			return null;
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					logger.error(ex.getMessage());
					return null;
				}
			}
		}
		String body = stringBuilder.toString();

		return body;
	}
	
	private String parseTlkmTselToXML(TlkmTsel tlkmTsel) {
		
		String xmlResult = null;
		
		System.out.println("Parsing Object TlkmTsel : "+tlkmTsel);

		StreamResult xmlStreamResult = new StreamResult(new ByteArrayOutputStream());

		try {
			JAXBContext jaxbContext = JAXBContext
					.newInstance(TlkmTsel.class);
			Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            
			jaxbMarshaller.marshal(tlkmTsel, xmlStreamResult);

			xmlResult = xmlStreamResult.getOutputStream().toString();
			return xmlResult;

		} catch (JAXBException e) {
			logger.error("Parse TlkmTsel to XML Failed TlkmTsel:"+tlkmTsel);
			e.printStackTrace();
			return null;
		}

	}
	
	private String parseTselTlkmToXML(TselTlkm tselTlkm) {
		
		String xmlResult = null;
		
		System.out.println("Parsing Object TlkmTsel : "+tselTlkm);

		StreamResult xmlStreamResult = new StreamResult(new ByteArrayOutputStream());

		try {
			JAXBContext jaxbContext = JAXBContext
					.newInstance(TselTlkm.class);
			Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            
			jaxbMarshaller.marshal(tselTlkm, xmlStreamResult);

			xmlResult = xmlStreamResult.getOutputStream().toString();
			return xmlResult;

		} catch (JAXBException e) {
			logger.error("Parse Tseltlkm to XML Failed Tseltlkm:"+tselTlkm);
			e.printStackTrace();
			return null;
		}

	}

	private TselTlkm parseXMLtoTselTlkm(String xml){
		
		System.out.println("Parsing XML : "+formatXML(xml));
		
		try {
			JAXBContext jc = JAXBContext.newInstance(TselTlkm.class);
	        Unmarshaller unmarshaller = jc.createUnmarshaller();
	        StreamSource xmlSource = new StreamSource(new StringReader(xml));
	        TselTlkm tsel = (TselTlkm)unmarshaller.unmarshal(xmlSource);
			return tsel;
		} catch (JAXBException e) {
			logger.error("Parse XML to TselTlkm Failed XML:\n"+formatXML(xml));
			logger.error(e.getMessage());
			return null;
		}
	}
	
	private String responseResult(String type, String responseStatus, String trxId){
		TlkmTsel tlkmTsel =  new TlkmTsel(type, new Parameter(trxId, responseStatus));
		String xml = parseTlkmTselToXML(tlkmTsel);
		return xml;
	}
	
	public String formatXML(String xml) {

		try {
			final InputSource src = new InputSource(new StringReader(xml));
			final Node document = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(src).getDocumentElement();
			final Boolean keepDeclaration = Boolean.valueOf(xml
					.startsWith("<?xml"));

			// May need this:
			// System.setProperty(DOMImplementationRegistry.PROPERTY,"com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl");

			final DOMImplementationRegistry registry = DOMImplementationRegistry
					.newInstance();
			final DOMImplementationLS impl = (DOMImplementationLS) registry
					.getDOMImplementation("LS");
			final LSSerializer writer = impl.createLSSerializer();

			writer.getDomConfig().setParameter("format-pretty-print",
					Boolean.TRUE); // Set this to true if the output needs to be
									// beautified.
			writer.getDomConfig().setParameter("xml-declaration",
					keepDeclaration); // Set this to true if the declaration is
										// needed to be outputted.

			return writer.writeToString(document);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public int parseHexaToDecimal (String hexa) {
		
		return Integer.parseInt(hexa, 16);
	}
	
	public String parseDecimalToHexa (int decimal) {
		
		return Integer.toHexString(decimal);
	}
	
}
